﻿namespace Warehouse

open System.Linq
open FSharp.Windows
open System.Collections.ObjectModel
open System
open Warehouse.DataModel

[<AbstractClass>]
[<AllowNullLiteral>]
type UpcModel() = 
    inherit EntityModel<DataModel.UPC>()

    abstract Code : string with get, set
    abstract Note : DataModel.UpcNote with get, set
    abstract Quantity : int with get, set

    override this.Init() = 
        this.Code <- this.Entity.Code
        this.Note <- this.Entity.UpcNote

    override this.Flush()=
        this.Entity.Code <- this.Code
        this.Entity.UpcNote <- this.Note

[<AbstractClass>]
[<AllowNullLiteral>]
type ProductModel() = 
    inherit EntityModel<DataModel.Product>()

    let RETAIL_PCT = 50. 
    let RETAIL_MIN_QUANTITY = 12.
    let RETAIL_MAX_QUANTITY = 24.

    //Entity mapping
    abstract SKU : string with get, set
    abstract ProductName : DataModel.ProductName with get, set

    abstract SizeOrColor : string with get, set
    abstract Unit : DataModel.Unit with get, set
    [<NotifyDependencyChanged>]
    member this.IsSizeOrColorEnable = this.Unit <> null && this.Unit.IsSizeOrColorRequired()
    [<NotifyDependencyChanged>]
    member this.SizeDisplay = (sprintf "%s %s" this.SizeOrColor this.Unit.Name).TrimStart()

    abstract ShopCost : decimal with get, set

    abstract UPCs : ObservableCollection<UpcModel> with get, set

    //Inventory screen details
    abstract TotalQuantity : int with get, set

    //Product edit
    //Lookups
    abstract Brands : DataModel.Brand[] with get, set
    abstract Categories : DataModel.Category[] with get, set
    abstract ProductNames : string[] with get, set
    abstract UnitLookup : DataModel.Unit[] with get, set
    abstract UpcNotes : DataModel.UpcNote seq with get, set

    abstract SelectedBrand : DataModel.Brand with get, set
    abstract SelectedCategory : DataModel.Category with get, set
    abstract SelectedProductName : string with get, set
    abstract SelectedUpc : UpcModel with get, set
    [<NotifyDependencyChanged>]
    member this.IsSetAsSKUEnable = 
        this.SelectedUpc <> null && this.SelectedUpc.Code <> this.SKU && isAdmin()

    //Supporting props
    member this.EditingMode = if this.IsNewEntity then "New Product" else "Editing Product" 

    //Monsoon props
    abstract DefaultBuy : decimal with get, set 
    abstract DefaultSell : decimal with get, set 

    member this.Classification = 
        match this.DefaultBuy with
        | GreaterThan 0M -> "A"
        | Between -30M 0M -> "B"
        | _ -> "C"

    member this.DisplaySize = if this.SizeOrColor <> null then this.SizeOrColor + " " + this.Unit.Name else null
    member this.Title = 
        seq {
            yield this.ProductName.Brand.Name
            yield this.ProductName.Name
            if this.DisplaySize <> null then yield this.DisplaySize
        } 
        |> String.concat " "

    override this.Init() = 
        this.SKU <- this.Entity.SKU
        this.ProductName <- this.Entity.ProductName
        this.SizeOrColor <- this.Entity.SizeOrColor
        this.Unit <- this.Entity.Unit
        this.ShopCost <- this.Entity.ShopCost

        this.UPCs <- this.Entity.UPCs |> Seq.map EntityModel.Load |> ObservableCollection.ofSeq

        this.SelectedProductName <- this.ProductName.Name
        this.SelectedBrand <- this.ProductName.Brand

        this.Compute()

    override this.Flush() =
        this.Entity.SKU <- this.SKU
        this.Entity.ProductName <- this.ProductName
        this.Entity.SizeOrColor <- this.SizeOrColor
        this.Entity.Unit <- this.Unit
        this.Entity.ShopCost <- this.ShopCost
        for upc in this.UPCs do 
            upc.UpdateEntity()
            upc.Entity.Product <- this.Entity

    override this.Compute() = 
        this.TotalQuantity <- this.UPCs |> Seq.sumBy (fun upc -> upc.Quantity)
        this.DefaultBuy <- this.ShopCost * ( 1M + this.Entity.DefaultBrandCommissionForVendor() / 100M) |> Decimal.round2
        this.DefaultSell <- this.ShopCost * ( 1M + this.Entity.DefaultBrandCommissionForClient() / 100M) |> Decimal.round2

    override this.HasErrors = 
        base.HasErrors || (this.UPCs |> Seq.exists (fun upc -> upc.HasErrors))


        
